﻿using System;
using System.Diagnostics;
using System.Drawing;

namespace EvoBoost.ComputerVision.ViolaJones
{
	public static class HaarFeature
	{
		private const int BadFeatureValue = 0;

		public static int Calculate(IntegralImage image, Rectangle rectangle, HaarFeatureType featureType)
		{
			if (!(new Rectangle(Point.Empty, image.Size).Contains(rectangle)))
				throw new ArgumentException("Given rectangle should be placed in image.", "rectangle");

			return CalculateNoCheck(image, rectangle, featureType);
		}

		internal static int CalculateNoCheck(IntegralImage image, Rectangle rectangle, HaarFeatureType featureType)
		{
			Debug.Assert(new Rectangle(Point.Empty, image.Size).Contains(rectangle));

			if (featureType == HaarFeatureType.TwoStripesHorizontal && rectangle.Height % 2 == 0)
			{
				Rectangle top = new Rectangle(rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height / 2);
				Rectangle bottom = new Rectangle(rectangle.Left, rectangle.Top + rectangle.Height / 2, rectangle.Width, rectangle.Height / 2);
				return image.CalculateSumNoCheck(top) - image.CalculateSumNoCheck(bottom);
			}
			
			if (featureType == HaarFeatureType.TwoStripesVertical && rectangle.Width % 2 == 0)
			{
				Rectangle left = new Rectangle(rectangle.Left, rectangle.Top, rectangle.Width / 2, rectangle.Height);
				Rectangle right = new Rectangle(rectangle.Left + rectangle.Width / 2, rectangle.Top, rectangle.Width / 2, rectangle.Height);
				return image.CalculateSumNoCheck(left) - image.CalculateSumNoCheck(right);
			}
			
			if (featureType == HaarFeatureType.ThreeStripesHorizontal && rectangle.Height % 3 == 0)
			{
				int step = rectangle.Height / 3;
				Rectangle top = new Rectangle(rectangle.Left, rectangle.Top, rectangle.Width, step);
				Rectangle middle = new Rectangle(rectangle.Left, rectangle.Top + step, rectangle.Width, step);
				Rectangle bottom = new Rectangle(rectangle.Left, rectangle.Top + step * 2, rectangle.Width, step);
				return
					image.CalculateSumNoCheck(top) + image.CalculateSumNoCheck(middle) - image.CalculateSumNoCheck(bottom);
			}
			
			if (featureType == HaarFeatureType.ThreeStripesVertical && rectangle.Width % 3 == 0)
			{
				int step = rectangle.Width / 3;
				Rectangle left = new Rectangle(rectangle.Left, rectangle.Top, step, rectangle.Height);
				Rectangle middle = new Rectangle(rectangle.Left + step, rectangle.Top, step, rectangle.Height);
				Rectangle right = new Rectangle(rectangle.Left + step * 2, rectangle.Top, step, rectangle.Height);
				return
					image.CalculateSumNoCheck(left) + image.CalculateSumNoCheck(right) - image.CalculateSumNoCheck(middle);
			}
			
			if (featureType == HaarFeatureType.FourSquares && rectangle.Width % 2 == 0 && rectangle.Height % 2 == 0)
			{
				int halfWidth = rectangle.Width / 2, halfHeight = rectangle.Height / 2;
				Rectangle topLeft = new Rectangle(rectangle.Left, rectangle.Top, halfWidth, halfHeight);
				Rectangle topRight = new Rectangle(rectangle.Left + halfWidth, rectangle.Top, halfWidth, halfHeight);
				Rectangle bottomLeft = new Rectangle(rectangle.Left, rectangle.Top + halfHeight, halfWidth, halfHeight);
				Rectangle bottomRight = new Rectangle(rectangle.Left + halfWidth, rectangle.Top + halfHeight, halfWidth, halfHeight);
				return
					image.CalculateSumNoCheck(topLeft) + image.CalculateSumNoCheck(bottomRight) -
					image.CalculateSumNoCheck(topRight) - image.CalculateSumNoCheck(bottomLeft);
			}
			
			return BadFeatureValue;
		}
	}
}